package com.wys.spring.controller.advice;

import com.wys.spring.SpringCommonProperties;
import com.wys.utils.JsonUtils;
import com.wys.utils.password.DESUtil;
import com.wys.utils.password.RSAUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.Locale;

@RestControllerAdvice(annotations = {RestController.class, Controller.class})
public class ControllerResponseBodyAdvice implements ResponseBodyAdvice<Object> {

    private final static Logger logger = LoggerFactory.getLogger(ControllerResponseBodyAdvice.class);

    private SpringCommonProperties.ResponseEncrypt responseEncrypt;

    private String excludeUrl;

    private static final String DES3_KEY = "sunnykakaking";

    public ControllerResponseBodyAdvice(SpringCommonProperties.ResponseEncrypt responseEncrypt) {
        this.responseEncrypt = responseEncrypt;
        excludeUrl = responseEncrypt.getExcludeUrls();
    }

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        if (!responseEncrypt.isEnable() || selectedContentType.includes(MediaType.MULTIPART_FORM_DATA)) {
            return body;
        }
        if (excludeUrl != null && excludeUrl.length() > 0) {
            logger.warn("Response Data Encrypt ExcludeUrl:{}, Request Url Path:{}", excludeUrl, request.getURI().getPath());
            for (String s : excludeUrl.split(",")) {
                if (request.getURI().getPath().startsWith(s.replace("/**", ""))) {
                    return body;
                }
            }
        }
        switch (responseEncrypt.getEncryptModel()) {
            case RSA:
                String rasBody=JsonUtils.object2Json(body);
                logger.warn("RSA encrypt before data:{}", rasBody);
                String pwdBody = RSAUtils.encryptHex(rasBody);
                logger.warn("RSA encrypt after data:{}", pwdBody);
                return pwdBody;
            case DES3:
                String des3=JsonUtils.object2Json(body);
                logger.warn("3DES encrypt before data:{}",des3);
                String pwdDESBody = DESUtil.encrypt3Des(DES3_KEY, des3);
                logger.warn("3DES encrypt after data:{}", pwdDESBody);
                return pwdDESBody;
            case SHA256:
                String shabody=JsonUtils.object2Json(body);
                logger.warn("SHA256 encrypt before data:{}",shabody );
                String sha256Body = DESUtil.encryptMI(shabody, SpringCommonProperties.ResponseEncrypt.EncryptModel.SHA256.name().toLowerCase(Locale.ROOT));
                logger.warn("SHA256 encrypt after data:{}", sha256Body);
                return sha256Body;
            default:
                return body;
        }
    }
}
